package sharewithus.content.dao.cacheimpl;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPool;
import sharewithus.content.dao.IFeedRelationshipCache;
import sharewithus.content.dao.cacheimpl.encoder.BeanEncoder;
import sharewithus.content.dto.Feed;
import sharewithus.content.dto.FeedRelationship;

public class FeedRelationshipCacheImpl implements IFeedRelationshipCache {

	private static final String REDIS_KEY_SUBCRIBER_PREX = "feedfr:";

	private static final String REDIS_KEY_USER_PREX = "feedowner:";

	private static final String REDIS_KEY_COMMENT_IDS_PREX = "feedCommentIds:";

	private static final String REDIS_KEY_COMMENT_COUNT_PREX = "feedCommentCount:";

	private static final String REDIS_KEY_FAVOR_FEED_ID_PREX = "feedFavorIds:";
	
	private static final String REDIS_KEY_USER_FEED_COUNT_PREX = "userFeedsCount:";

	@Autowired
	@Qualifier("shardedJedisPool")
	private ShardedJedisPool jedisMgr;

	@Autowired
	private BeanEncoder<FeedRelationship> feedRelationshipEncoder;

	public List<FeedRelationship> getSubscribedFeeds(String subscriberId) {
		return getSubscribedFeeds(subscriberId, -1, -1);

	}

	public List<FeedRelationship> getSubscribedFeeds(String subscriberId,
			int pageSize, int pageNumber) {
		ShardedJedis jedis = null;
		List<FeedRelationship> frList = new LinkedList<FeedRelationship>();
		String frListKey = REDIS_KEY_SUBCRIBER_PREX + subscriberId;

		List<String> frJsons = null;
		try {
			jedis = jedisMgr.getResource();
			if (pageSize >= 0 && pageNumber >= 0) {
				long savedSize = jedis.llen(frListKey);

				long startNumber = pageSize * (pageNumber - 1);
				long endNumber = pageSize * pageNumber - 1;

				if (savedSize > endNumber) {
					frJsons = jedis.lrange(frListKey, startNumber, endNumber);
				}
				if (startNumber <= savedSize && savedSize <= endNumber) {
					frJsons = jedis.lrange(frListKey, startNumber, -1);
				} else {
					// feedJsons = jedis.lrange(feedListKey, 0, -1);
				}
			} else {
				frJsons = jedis.lrange(frListKey, 0, -1);
			}
		} finally {
			if (jedis != null)
				jedisMgr.returnResource(jedis);
		}

		Iterator<String> iter = frJsons.iterator();
		String frJson = null;
		while (iter.hasNext()) {
			frJson = iter.next();
			if (frJson != null && !"".equals(frJson)) {
				frList.add(feedRelationshipEncoder.parseJson(frJson));
			}
		}
		return frList;

	}

	public void saveSubscriberFeeds(String subscriberId, Feed feed) {
		String frListKey = REDIS_KEY_SUBCRIBER_PREX + subscriberId;
		ShardedJedis jedis = null;
		try {
			jedis = jedisMgr.getResource();
			FeedRelationship fr = new FeedRelationship();
			fr.setFeedId(feed.getFeedId());
			fr.setFeedOwnerId(feed.getOwnerId());
			fr.setSubscribeUserId(subscriberId);

			jedis.lpush(frListKey, feedRelationshipEncoder.getFrJson(fr));
		} finally {
			if (jedis != null)
				jedisMgr.returnResource(jedis);
		}

	}

	public void pushUserFeedRelationship(Feed feed) {
		String feedListKey = REDIS_KEY_USER_PREX + feed.getOwnerId();
		ShardedJedis jedis = null;
		try {
			jedis = jedisMgr.getResource();
			jedis.lpush(feedListKey, feed.getFeedId());
		} finally {
			if (jedis != null)
				jedisMgr.returnResource(jedis);
		}
	}

	public List<String> getUserFeedIds(String userId) {

		return getUserFeedPageIds(userId, -1, -1);
	}

	public List<String> getUserFeedPageIds(String userId, int pageSize,
			int pageNumber) {
		String feedListKey = REDIS_KEY_USER_PREX + userId;
		ShardedJedis jedis = null;
		List<String> feedIds = new LinkedList<String>();
		try {
			jedis = jedisMgr.getResource();
			long savedSize = jedis.llen(feedListKey);
			long startNumber, endNumber;
			if (pageSize != -1 && pageNumber != -1) {
				startNumber = pageSize * (pageNumber - 1);
				endNumber = pageSize * pageNumber - 1;
			} else {
				startNumber = 0;
				endNumber = -1;
			}
			if (savedSize > endNumber) {
				feedIds = jedis.lrange(feedListKey, startNumber, endNumber);
			} else if (startNumber <= savedSize && savedSize <= endNumber) {
				feedIds = jedis.lrange(feedListKey, startNumber, -1);
			} else {
				// feedJsons = jedis.lrange(feedListKey, 0, -1);
			}
		} finally {
			if (jedis != null)
				jedisMgr.returnResource(jedis);
		}
		return feedIds;
	}

	public void pushFeedCommentRelation(Feed commentFeed) {
		
		if (commentFeed.getCommentedFeedId() == null
				|| "".equals(commentFeed.getCommentedFeedId())) {
			return;
		}
		
		String key = REDIS_KEY_COMMENT_IDS_PREX
				+ commentFeed.getCommentedFeedId();

		ShardedJedis jedis = null;
		try {
			jedis = jedisMgr.getResource();

			jedis.lpush(key, commentFeed.getFeedId());
		} finally {
			if (jedis != null)
				jedisMgr.returnResource(jedis);
		}
	}

	public List<String> listCommentIds(String feedId) {
		return listCommentIds(feedId, -1, -1);
	}
	
	


	public List<String> listCommentIds(String feedId, int pageSize,
			int pageNumber) {
		String key = REDIS_KEY_COMMENT_IDS_PREX + feedId;
		ShardedJedis jedis = null;
		List<String> feedIds = null;
		try {
			jedis = jedisMgr.getResource();
			if (pageSize >= 0 && pageNumber >= 0) {
				long savedSize = jedis.llen(key);

				long startNumber = pageSize * (pageNumber - 1);
				long endNumber = pageSize * pageNumber - 1;

				if (savedSize > endNumber) {
					feedIds = jedis.lrange(key, startNumber, endNumber);
				}
				if (startNumber <= savedSize && savedSize <= endNumber) {
					feedIds = jedis.lrange(key, startNumber, -1);
				} else {
					// feedJsons = jedis.lrange(feedListKey, 0, -1);
				}
			} else {
				feedIds = jedis.lrange(key, 0, -1);
			}
		} finally {
			if (jedis != null)
				jedisMgr.returnResource(jedis);
		}

		return feedIds;
	}

	public void incrCommentsCount(String feedId) {
		String key = REDIS_KEY_COMMENT_COUNT_PREX + feedId;
		ShardedJedis jedis = null;
		try {
			jedis = jedisMgr.getResource();
			jedis.incr(key);
		} finally {
			if (jedis != null)
				jedisMgr.returnResource(jedis);
		}

	}

	public void decrCommentsCount(String feedId) {
		String key = REDIS_KEY_COMMENT_COUNT_PREX + feedId;
		ShardedJedis jedis = null;
		try {
			jedis = jedisMgr.getResource();
			jedis.decr(key);
		} finally {
			if (jedis != null)
				jedisMgr.returnResource(jedis);
		}
	}

	public int getCommentsCount(String feedId){
		String key = REDIS_KEY_COMMENT_IDS_PREX + feedId;
		ShardedJedis jedis = null;
		String countString =null;
		try {
			jedis = jedisMgr.getResource();
			countString = jedis.get(key);
		} finally {
			if (jedis != null)
				jedisMgr.returnResource(jedis);
		}
		if(countString==null){
			return 0;
		}
		else{
			return Integer.valueOf(countString).intValue();
		}
	}
	
	public void favorFeed(String feedId, String userId) {
		String key = REDIS_KEY_FAVOR_FEED_ID_PREX + userId;

		ShardedJedis jedis = null;
		try {
			jedis = jedisMgr.getResource();
			jedis.lpush(key, feedId);
		} finally {
			if (jedis != null)
				jedisMgr.returnResource(jedis);
		}

	}

	public void unFavorFeed(String feedId, String userId) {
		String key = REDIS_KEY_FAVOR_FEED_ID_PREX + userId;

		ShardedJedis jedis = null;
		try {
			jedis = jedisMgr.getResource();
			jedis.lrem(key, 0, feedId);
		} finally {
			if (jedis != null)
				jedisMgr.returnResource(jedis);
		}
	}

	public List<String> getFavorFeedIds(String userId) {
		// TODO Auto-generated method stub
		return getFavorFeedIds(userId, -1, -1);
	}
	
	public List<String> getFavorFeedIds(String userId, int pageSize, int pageNumber) {
		String key = REDIS_KEY_FAVOR_FEED_ID_PREX + userId;
		ShardedJedis jedis = null;
		List<String> feedIds = null;
		try {
			jedis = jedisMgr.getResource();
			if (pageSize >= 0 && pageNumber >= 0) {
				long savedSize = jedis.llen(key);

				long startNumber = pageSize * (pageNumber - 1);
				long endNumber = pageSize * pageNumber - 1;

				if (savedSize > endNumber) {
					feedIds = jedis.lrange(key, startNumber, endNumber);
				}
				if (startNumber <= savedSize && savedSize <= endNumber) {
					feedIds = jedis.lrange(key, startNumber, -1);
				} else {
					// feedJsons = jedis.lrange(feedListKey, 0, -1);
				}
			} else {
				feedIds = jedis.lrange(key, 0, -1);
			}
		} finally {
			if (jedis != null)
				jedisMgr.returnResource(jedis);
		}

		return feedIds;
	}

	public int getUserFeedCount(String userId) {
		String key = REDIS_KEY_USER_FEED_COUNT_PREX + userId;
		ShardedJedis jedis = null;
		String countString =null;
		try {
			jedis = jedisMgr.getResource();
			countString = jedis.get(key);
		} finally {
			if (jedis != null)
				jedisMgr.returnResource(jedis);
		}
		
		if(countString==null){
			return 0;
		}
		else{
			return Integer.valueOf(countString).intValue();
		}
	}

	public void incrUserFeedCount(String userId) {
		String key = REDIS_KEY_USER_FEED_COUNT_PREX + userId;
		ShardedJedis jedis = null;
		try {
			jedis = jedisMgr.getResource();
			jedis.incr(key);
		} finally {
			if (jedis != null)
				jedisMgr.returnResource(jedis);
		}
	}

	public void decrUserFeedCount(String userId) {
		String key = REDIS_KEY_USER_FEED_COUNT_PREX + userId;
		ShardedJedis jedis = null;
		try {
			jedis = jedisMgr.getResource();
			jedis.decr(key);
		} finally {
			if (jedis != null)
				jedisMgr.returnResource(jedis);
		}
	}

}
